package site.wlwsjsx.iot_backend.mapper;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import site.wlwsjsx.iot_backend.entity.AlertEvent;
import site.wlwsjsx.iot_backend.mapper.AlertEventMapper;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
public class AlertEventMapperTest {

    @Autowired
    private AlertEventMapper alertEventMapper;

    private AlertEvent testEvent1;
    private AlertEvent testEvent2;
    private LocalDateTime baseTime;

    @BeforeEach
    void setUp() {
        // 初始化测试时间
        baseTime = LocalDateTime.of(2023, 10, 15, 10, 0);

        // 创建测试数据1
        testEvent1 = new AlertEvent();
        testEvent1.setDeviceId("device-001");
        testEvent1.setAlertType("OVER_TEMP");
        testEvent1.setSeverity("HIGH");
        testEvent1.setSensorValue(30.5f);
        testEvent1.setThreshold(25.0f);
        testEvent1.setUsername("testUser");
        testEvent1.setTemperature(30.5f);
        testEvent1.setHumidity(45.0f);
        testEvent1.setFlameScope(0.0f);
        testEvent1.setSmokeScope(0.1f);
        testEvent1.setCreateTime(baseTime);
        testEvent1.setProcessed(0);

        // 创建测试数据2
        testEvent2 = new AlertEvent();
        testEvent2.setDeviceId("device-002");
        testEvent2.setAlertType("SMOKE");
        testEvent2.setSeverity("MEDIUM");
        testEvent2.setSensorValue(0.8f);
        testEvent2.setThreshold(0.5f);
        testEvent2.setUsername("testUser");
        testEvent2.setTemperature(22.0f);
        testEvent2.setHumidity(50.0f);
        testEvent2.setFlameScope(0.0f);
        testEvent2.setSmokeScope(0.8f);
        testEvent2.setCreateTime(baseTime.plusHours(1));
        testEvent2.setProcessed(0);

        // 插入测试数据
        alertEventMapper.insert(testEvent1);
        alertEventMapper.insert(testEvent2);

        // 获取自动生成的ID
        Long id1 = testEvent1.getId();
        Long id2 = testEvent2.getId();
        assertNotNull(id1, "插入后ID不应为null");
        assertNotNull(id2, "插入后ID不应为null");
    }

    @AfterEach
    void tearDown() {
        // 清理测试数据
        if (testEvent1.getId() != null) {
            alertEventMapper.deleteById(testEvent1.getId());
        }
        if (testEvent2.getId() != null) {
            alertEventMapper.deleteById(testEvent2.getId());
        }
    }

    @Test
    void testInsert() {
        // 创建新的测试事件
        AlertEvent newEvent = new AlertEvent();
        newEvent.setDeviceId("device-003");
        newEvent.setAlertType("FLAME");
        newEvent.setSeverity("CRITICAL");
        newEvent.setCreateTime(LocalDateTime.now());
        newEvent.setProcessed(0);

        // 执行插入
        int result = alertEventMapper.insert(newEvent);
        assertEquals(1, result, "插入应影响1行数据");

        // 验证插入成功
        Long newEventId = newEvent.getId();
        assertNotNull(newEventId, "插入后应生成ID");

        // 清理
        alertEventMapper.deleteById(newEventId);
    }

    @Test
    void testSelectLatestByDeviceId() {
        // 测试存在的设备
        AlertEvent latest = alertEventMapper.selectLatestByDeviceId("device-001");
        assertNotNull(latest, "应查询到设备device-001的最新告警");
        assertEquals("OVER_TEMP", latest.getAlertType());

        // 测试不存在的设备
        AlertEvent nonExistent = alertEventMapper.selectLatestByDeviceId("device-999");
        assertNull(nonExistent, "不存在的设备应返回null");
    }

    @Test
    void testCountByCondition() {
        // 测试1: 设备ID+严重程度组合
        Long count1 = alertEventMapper.countByCondition(
                "device-001", null, "HIGH", null, null);
        assertEquals(1L, count1, "设备device-001的HIGH级别告警应返回1");

        // 测试2: 告警类型条件
        Long count2 = alertEventMapper.countByCondition(
                null, "SMOKE", null, null, null);
        assertEquals(1L, count2, "SMOKE类型告警应返回1");

        // 测试3: 时间范围条件
        LocalDateTime start = baseTime.minusMinutes(30);
        LocalDateTime end = baseTime.plusMinutes(30);
        Long count3 = alertEventMapper.countByCondition(
                null, null, null, start, end);
        assertEquals(1L, count3, "时间范围内应返回1条记录");

        // 测试4: 组合条件
        Long count4 = alertEventMapper.countByCondition(
                "device-002", "SMOKE", "MEDIUM", null, null);
        assertEquals(1L, count4, "组合条件应返回1条记录");

        // 测试5: 无匹配条件
        Long count5 = alertEventMapper.countByCondition(
                "device-999", null, null, null, null);
        assertEquals(0L, count5, "无匹配条件应返回0");
    }

    @Test
    void testSelectByCondition() {
        // 测试分页查询
        List<AlertEvent> events = alertEventMapper.selectByCondition(
                null, null, null, null, null, 0, 10);
        assertTrue(events.size() >= 2, "至少应查询到2条测试数据");

        // 测试设备ID条件
        List<AlertEvent> deviceEvents = alertEventMapper.selectByCondition(
                "device-001", null, null, null, null, 0, 10);
        assertEquals(1, deviceEvents.size(), "设备device-001应返回1条记录");
        assertEquals("device-001", deviceEvents.get(0).getDeviceId());
    }

    @Test
    void testUpdateProcessedStatus() {
        // 测试单条更新
        int result = alertEventMapper.updateProcessedStatus(testEvent1.getId(), 1);
        assertEquals(1, result, "应更新1条记录");

        // 验证更新结果
        AlertEvent updated = alertEventMapper.selectLatestByDeviceId("device-001");
        assertEquals(1, updated.getProcessed(), "处理状态应更新为1");

        // 测试批量更新
        List<Long> ids = Arrays.asList(testEvent1.getId(), testEvent2.getId());
        int batchResult = alertEventMapper.batchUpdateProcessedStatus(ids, 2);
        assertEquals(2, batchResult, "应批量更新2条记录");
    }

    @Test
    void testDeleteById() {
        Long eventId = testEvent1.getId();
        int result = alertEventMapper.deleteById(eventId);
        assertEquals(1, result, "应删除1条记录");

        // 验证删除结果
        AlertEvent deleted = alertEventMapper.selectLatestByDeviceId("device-001");
        assertNull(deleted, "删除后不应再查询到记录");

        // 清理时不会再删除已删除的记录
        testEvent1.setId(null);
    }
}
    